本文接續前一篇文章Day5
今天的code會從
https://github.com/mars1120/jetpackMvvmDemo/tree/Databinding
開branch繼續往下修改
今天會將click事件改成databinding型式
首先先替textview新增一個click事件
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
...
val tv: TextView = activity!!.findViewById(R.id.message)
tv.setOnClickListener {
previewViewModel.message++
}
}
功能是textview點擊以後 顯示的文字訊息會變更
例如變成
message:0 -> message:1 -> message:2
接著馬上來運行專案
會發現點擊以後資料並沒有更新
那我們有兩個辦法來通知UI要更新數據
第一個是數據變更以後呼叫binding().invalidateAll()
但如果每次更新都要呼叫一次也太麻煩
所以接著要導入liveData讓他自動通知
先來修改viewModel
PreviewViewModel.kt
class PreviewViewModel : ViewModel() {
private val _message = MutableLiveData(0)
val message: LiveData<Int> = _message
fun onUpdateMessage(int: Int) {
_message.value = int
}
}
接著調整fragment
PreviewFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
var binding: PreviewFragmentBinding =
DataBindingUtil.inflate(inflater, R.layout.preview_fragment, container, false)
var rootView: View = binding.root
// setting values to model
binding.viewModel = previewViewModel
//注意要跟生命週期綁定 不然數據不會更新
binding.setLifecycleOwner(this)
return rootView
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
previewViewModel.onUpdateMessage(getArguments()?.getInt(ARG_PAGE) ?: 0)
val tv: TextView = activity!!.findViewById(R.id.message)
tv.setOnClickListener {
var mMessage = previewViewModel.message.value
previewViewModel.onUpdateMessage(mMessage!! + 1)
}
接著我們把click行為也轉移到viewModel去
PreviewViewModel.kt
fun onClick() {
_message.value = _message.value!! + 1
}
Fragment的click宣告就可以移掉了
PreviewFragment.kt
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
previewViewModel.onUpdateMessage(getArguments()?.getInt(ARG_PAGE) ?: 0)
}
接著去xml串接
preview_fragment.xml
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{`message:`+String.valueOf(viewModel.message)}"
android:onClick="@{() -> viewModel.onClick()}"
/>
然後發現fragment頁變得前所未有的清爽(?
那如果想要綁定更多行為呢?
例如說今天我想要textview根據message的數字去改變顯示的顏色
先去build.gradle 新增plugin
build.gradle(module:app)
apply plugin: 'kotlin-kapt'
...
android {
...
接著新增一個BindingAdapters.kt
BindingAdapters.kt
@BindingAdapter("app:textCurrentColor")
fun textCurrentColor(view: View, intMessage: Int) {
val colorBlack = ContextCompat.getColor(view.context, android.R.color.black)
val colorPrimary = ContextCompat.getColor(view.context, R.color.colorPrimary)
if (intMessage > 5)
(view as TextView).setTextColor(colorPrimary)
else
(view as TextView).setTextColor(colorBlack)
}
fun名稱自訂 不要重複就可
@BindingAdapter("XXXXX")
決定在xml顯示的名稱
接著去xml更新textview
preview_fragment.xml
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{`message:`+String.valueOf(viewModel.message)}"
android:onClick="@{() -> viewModel.onClick()}"
app:textCurrentColor="@{viewModel.message}"
/>
這個功能是點擊一定次數後文字顏色會改變
這樣就完成雙向綁定了
今天的代碼
https://github.com/mars1120/jetpackMvvmDemo/tree/databinding-2